package cool.taomu.toolkit.hikaricp.module

import com.google.inject.Key
import com.google.inject.PrivateModule
import com.google.inject.TypeLiteral
import com.google.inject.multibindings.MapBinder
import com.google.inject.multibindings.OptionalBinder
import com.google.inject.name.Names
import cool.taomu.toolkit.TaomuConfigure
import cool.taomu.toolkit.annotations.datasource.Primary
import cool.taomu.toolkit.entity.DataSourceConfigEntity
import cool.taomu.toolkit.entity.DataSourceConfigEntity.PoolType
import cool.taomu.toolkit.hikaricp.provider.HikariProvider
import java.util.Map
import javax.sql.DataSource
import org.apache.commons.beanutils.BeanUtils
import org.slf4j.LoggerFactory

class HikariModule extends PrivateModule {
   val static LOG = LoggerFactory.getLogger(HikariModule)
    TaomuConfigure config

    new(TaomuConfigure config) {
        this.config = config
    }
    
    override protected configure() {
         config.binder("taomu.datasource", [
            if (it instanceof Map) {
                if (it.containsKey("poolType")) {
                    var configRef = new DataSourceConfigEntity()
                    BeanUtils.populate(configRef, it);
                    if (PoolType.valueOf(configRef.poolType.toUpperCase).equals(PoolType.HIKARI)) {
                        LOG.info("加载数据库连接池:{}",configRef.poolType.toLowerCase)
                        var key = #["taomu.datasource.name", it.get("name")].join(".")
                        var ds = new HikariProvider(configRef)
                        bind(DataSource).annotatedWith(Names.named(key)).toProvider(ds).asEagerSingleton
                        OptionalBinder.newOptionalBinder(binder(), Key.get(
                            DataSource,
                            Primary
                        )).setDefault().toProvider(ds).asEagerSingleton

                        if (this.config.mapBinder === null) {
                            this.config.mapBinder = MapBinder.newMapBinder(binder(), String, DataSource);
                        }
                        var MapBinder<String, DataSource> binder = this.config.mapBinder
                        binder.addBinding(key).toProvider(ds).asEagerSingleton
                        expose(Key.get(DataSource, Primary))
                        expose(Key.get(DataSource, Names.named(key)))
                        expose(new TypeLiteral<Map<String, DataSource>>() {
                        });
                    }
                }
            }
        ])
    }
    
}